package com.familyigo.gdemo;

import org.antlr.runtime.tree.CommonTree;
import org.apache.commons.jexl3.*;
import org.jdbi.v3.core.statement.StatementContext;
import org.jdbi.v3.core.statement.TemplateEngine;
import org.jdbi.v3.core.statement.UnableToCreateStatementException;
import org.jdbi.v3.core.statement.UnableToExecuteStatementException;
import org.jdbi.v3.stringtemplate4.StringTemplates;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STErrorListener;
import org.stringtemplate.v4.STGroup;
import org.stringtemplate.v4.compiler.CompiledST;
import org.stringtemplate.v4.misc.STMessage;

import java.util.List;
import java.util.Map;

public class JexlAwareStringTemplateEngine implements TemplateEngine {
    private final JexlEngine jexlEngine;

    public JexlAwareStringTemplateEngine() {
        this.jexlEngine = new JexlBuilder().cache(512).strict(true).create();
    }


    @Override
    public String render(String sql, StatementContext ctx) {
        STGroup group = new STGroup();
        group.setListener(new JexlAwareStringTemplateEngine.ErrorListener(ctx));
        ST template = new ST(group, sql);
        if (sql.contains("if")) {
            System.out.println("if 表达式");
        }
        //add by walden
        CompiledST compiledST = template.impl;
        List<?> children = compiledST.ast.getChildren();
        if (children != null) {
            children.forEach(node -> {
                if (node instanceof CommonTree) {
                }
            });
        }
        Map<String, Object> attributes = ctx.getAttributes();

        attributes.forEach(template::add);

        return template.render();
    }

    static class ErrorListener implements STErrorListener {
        private final StatementContext ctx;

        ErrorListener(StatementContext ctx) {
            this.ctx = ctx;
        }

        public void compileTimeError(STMessage msg) {
            throw new UnableToCreateStatementException("Compiling StringTemplate failed: " + String.valueOf(msg), msg.cause, this.ctx);
        }

        public void runTimeError(STMessage msg) {
            switch (msg.error) {
                case NO_SUCH_ATTRIBUTE:
                    if (((StringTemplates) this.ctx.getConfig(StringTemplates.class)).isFailOnMissingAttribute()) {
                        break;
                    }
                case NO_SUCH_PROPERTY:
                    return;
            }

            throw new UnableToExecuteStatementException("Executing StringTemplate failed: " + String.valueOf(msg), msg.cause, this.ctx);
        }

        public void IOError(STMessage msg) {
            this.runTimeError(msg);
        }

        public void internalError(STMessage msg) {
            this.runTimeError(msg);
        }
    }
}
